package com.hcnow.common.utils

import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import java.util.HashMap
import com.auth0.jwt.JWTSigner
import com.auth0.jwt.JWTVerifier
import com.auth0.jwt.internal.com.fasterxml.jackson.databind.ObjectMapper
import com.hcnow.common.Exception.AuthorizationException

object JWTUtils {

    private val SECRET = "zclf&hcnow";
    private val EXP = "exp";
    private val ISS = "iss";
    private val PAYLOAD = "payload";

    fun <T> sign(`object`: T, maxAge: Long): String {
        try {
            val signer = JWTSigner(SECRET);
            val claims = HashMap<String, Any>();
            val mapper = ObjectMapper();
            val jsonString = mapper.writeValueAsString(`object`);
            claims[PAYLOAD] = jsonString;
            claims[EXP] = System.currentTimeMillis() + maxAge;  //过期时间
            claims[ISS] = "hcnow"; //JWT的签发者
            return signer.sign(claims);
        } catch (e: Exception) {
            return "";
        }

    }

    fun <T> unsign(jwt: String, classT: Class<T>): T? {
        val verifier = JWTVerifier(SECRET);
        try {
            val claims = verifier.verify(jwt);
            if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
                val exp = claims[EXP] as Long;
                val currentTimeMillis = System.currentTimeMillis();
                if (exp > currentTimeMillis) {
                    val json = claims[PAYLOAD] as String;
                    val objectMapper = ObjectMapper();
                    return objectMapper.readValue(json, classT);
                }
            }
            return null;
        } catch (e: Exception) {
            return null;
        }
    }

    fun  getProjectIdByToken(jwt: String): String {
        try {
            val verifier = JWTVerifier(SECRET);
            val claims = verifier.verify(jwt);
            if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
                val exp = claims[EXP] as Long;
                val currentTimeMillis = System.currentTimeMillis();
                if (exp > currentTimeMillis) {
                    val token:String = claims[PAYLOAD] as String;
                    val jsonObject:JSONObject = JSON.parseObject(token);
                    return jsonObject?.get("projectId").toString();
                }
            }
            throw AuthorizationException("token is not valid");
        } catch (e: Exception) {
            throw AuthorizationException("token is not valid");
        }
    }


    fun  validateToken(jwt: String): Boolean {
        val verifier = JWTVerifier(SECRET);
        try {
            val claims = verifier.verify(jwt);
            if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
                val exp = claims[EXP] as Long;
                if (exp < System.currentTimeMillis()) {
                   return false;
                }
            }
            return true;
        } catch (e: Exception) {
            e.printStackTrace()
            return false;
        }
    }

}
